import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class BoardGUI extends JPanel implements ActionListener {	
	
	private Board board;
	private static Player[] players;
	private Token token = new Token();
	private Dice dice;
	
	private String boardURL;
	private String[] diceURL = new String[6];
	private String[] tokenURL;
	
	static DisplayMode displayMode = new DisplayMode(1024, 800, 16, DisplayMode.REFRESH_RATE_UNKNOWN);
	static SimpleScreenManager screen;

	static JFrame frame;
	static JLayeredPane layeredPane;
	static JLabel boardLabel;
	static JLabel tokenLabel[];
	static JLabel deedLabel = new JLabel();
	static JLabel textLabel = new JLabel();
	
	static JLabel playerName;
	static JLabel playerCash;
		
	static JLabel diceLabel[] = new JLabel[2];
	
	static JButton rollButton;
	static JButton fineButton;
	static JButton useCardButton;
	static JButton buyCardButton;
	static JButton endTurnButton;
	static JButton propertiesButton;
	static JButton deedsButton;
	static JButton bankruptButton;
		
	public BoardGUI(Board board) {
		
		this.board = board;
		dice = board.getDice();
		players = board.getPlayers();
				
		this.loadImages();
		
		frame = new JFrame("Monopoly");
		frame.setPreferredSize(new Dimension(1280, 800));
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		this.run(displayMode);
		
		layeredPane = new JLayeredPane();
        layeredPane.setPreferredSize(new Dimension(1280, 800));
				
		boardLabel = new JLabel(createImageIcon(boardURL));
		
		playerName = new JLabel(players[0].getName() + "'s turn");
		playerName.setFont(new Font("Serif", Font.BOLD, 48));
		
		playerCash = new JLabel("Cash: " + Integer.toString(players[0].getCash()));
		playerCash.setFont(new Font("Serif", Font.ITALIC, 20));
		
		tokenLabel = new JLabel[board.getPlayerCount()];
		
		for (int y = 0; y < board.getPlayerCount(); y++) {
			
			tokenLabel[y] = new JLabel(createImageIcon(tokenURL[y]));
			tokenLabel[y].setBounds(players[y].getXLocation(), players[y].getYLocation(), 15, 14);
			layeredPane.add(tokenLabel[y], new Integer(y+1), 0);
		}
		
		diceLabel[0] = new JLabel(createImageIcon(diceURL[0]));
		
		diceLabel[1] = new JLabel(createImageIcon(diceURL[0]));
		
		rollButton = new JButton("Roll Dice");
		rollButton.setMnemonic(KeyEvent.VK_M);
		rollButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rollButtonActionPerformed(evt);
            }
        });
		
		fineButton = new JButton("Pay Fine");
		fineButton.setEnabled(false);
		fineButton.setVisible(false);
		fineButton.setMnemonic(KeyEvent.VK_M);
		fineButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
            	fineButtonActionPerformed(evt);
            }
        });
		
		useCardButton = new JButton("Use Get Out of Jail Card");
		useCardButton.setEnabled(false);
		useCardButton.setVisible(false);
		useCardButton.setMnemonic(KeyEvent.VK_M);
		useCardButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
            	useCardButtonActionPerformed(evt);
            }
        });
		
		buyCardButton = new JButton("Buy Get Out of Jail Card");
		buyCardButton.setEnabled(false);
		buyCardButton.setVisible(false);
		buyCardButton.setMnemonic(KeyEvent.VK_M);
		buyCardButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
            	buyCardButtonActionPerformed(evt);
            }
        });
		
		endTurnButton = new JButton("End Turn");
		endTurnButton.setEnabled(false);
		endTurnButton.setMnemonic(KeyEvent.VK_M);
		endTurnButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
            	endTurnButtonActionPerformed(evt);
            }
        });
		
		propertiesButton = new JButton("View Properties");
		propertiesButton.setMnemonic(KeyEvent.VK_M);
		propertiesButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
            	propertiesButtonActionPerformed(evt);
            }
        });
		
		deedsButton = new JButton("View Deeds");
		deedsButton.setMnemonic(KeyEvent.VK_M);
		deedsButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
            	deedsButtonActionPerformed(evt);
            }
        });
		
		bankruptButton = new JButton("Declare Bankruptcy");
		bankruptButton.setMnemonic(KeyEvent.VK_M);
		bankruptButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
            	bankruptButtonActionPerformed(evt);
            }
        });
		
		//Coordinates
		boardLabel.setBounds(5, 5, 779, 778);
		
		playerName.setBounds(790, 5, 600, 60);
		playerCash.setBounds(790, 50, 600, 60);
		
        diceLabel[0].setBounds(795, 105, 41, 42);
        diceLabel[1].setBounds(841, 105, 41, 42);
        
		rollButton.setBounds(790, 157, 100, 25);
		fineButton.setBounds(790, 191, 100, 25);
		useCardButton.setBounds(899, 191, 170, 25);
		buyCardButton.setBounds(899, 191, 170, 25);
		endTurnButton.setBounds(899, 157, 100, 25);
		deedsButton.setBounds(790, 759, 125, 25);
		propertiesButton.setBounds(920, 759, 125, 25);
		bankruptButton.setBounds(1050, 759, 170, 25);
		
		layeredPane.add(boardLabel, new Integer(0), 0);
		layeredPane.add(playerName, new Integer(0), 0);
		layeredPane.add(playerCash, new Integer(0), 0);
		layeredPane.add(rollButton, new Integer(0), 0);
		layeredPane.add(fineButton, new Integer(0), 0);
		layeredPane.add(useCardButton, new Integer(0), 0);
		layeredPane.add(buyCardButton, new Integer(0), 0);
		layeredPane.add(endTurnButton, new Integer(0), 0);
		layeredPane.add(deedsButton, new Integer(0), 0);
		layeredPane.add(propertiesButton, new Integer(0), 0);
		layeredPane.add(bankruptButton, new Integer(0), 0);
		layeredPane.add(diceLabel[0], new Integer(0), 0);
		layeredPane.add(diceLabel[1], new Integer(0), 0);
		
		frame.getContentPane().add(layeredPane);
		
		frame.pack(); 
		frame.setVisible(true);
	}
	
	public void run(DisplayMode displayMode) {
	
        screen = new SimpleScreenManager();
		
        try {
            
			screen.setFullScreen(displayMode, frame);
        }
		
        finally {
     
			screen.restoreScreen();
        }
    }
	
	public void actionPerformed(ActionEvent e) {
        
    }
	
	private void rollButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
		
		rollButton.setEnabled(false);
		
		this.rollDice();
		this.moveToken();	
		board.nextPlayer();
		
		fineButton.setEnabled(false);
		endTurnButton.setEnabled(true);
    }
	
	private void fineButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
		
		Jail.payFine(players[board.getCurrentPlayer()]);
		players[board.getCurrentPlayer()].setJail(false);
		players[board.getCurrentPlayer()].resetLastThreeRolls();
		
		playerCash.setText("Cash: " + Integer.toString(players[board.getCurrentPlayer()].getCash()));
		playerCash.repaint();
		
		fineButton.setEnabled(false);
    }

	private void useCardButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
		
		players[board.getCurrentPlayer()].setJail(false);
		players[board.getCurrentPlayer()].resetLastThreeRolls();
		
		if (players[board.getCurrentPlayer()].getOutOfJailCard1() == true) {
		
			players[board.getCurrentPlayer()].setOutOfJailCard1(false);
			Chance.setJailCard(false);
		}
		
		else {
			
			players[board.getCurrentPlayer()].setOutOfJailCard2(false);
			CommunityChest.setJailCard(false);
		}
		
		fineButton.setEnabled(false);
    }
	
	private void buyCardButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
		
    }
	
	private void endTurnButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
		
		fineButton.setVisible(false);
		useCardButton.setVisible(false);
		buyCardButton.setVisible(false);
		
		rollButton.setEnabled(true);
		deedsButton.setEnabled(true);
		propertiesButton.setEnabled(true);
		bankruptButton.setEnabled(true);
		
		playerName.setText(players[board.getCurrentPlayer()].getName() + "'s turn");
		playerName.repaint();
		
		playerCash.setText("Cash: " + Integer.toString(players[board.getCurrentPlayer()].getCash()));
		playerCash.repaint();
		
		rollButton.setEnabled(true);
		endTurnButton.setEnabled(false);
		
		if (players[board.getCurrentPlayer()].getJail() == true) {
			
			fineButton.setVisible(true);
			fineButton.setEnabled(true);
			
			if (players[board.getCurrentPlayer()].getOutOfJailCard1() == true || players[board.getCurrentPlayer()].getOutOfJailCard2() == true) {
				
				useCardButton.setVisible(true);
				useCardButton.setEnabled(true);
			}
			
			else {
				
				buyCardButton.setVisible(true);
				buyCardButton.setEnabled(true);
			}
		}
    }
	
	private void propertiesButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
		
		new ViewPropertiesGUI(players[board.getCurrentPlayer()]);
    }

	private void deedsButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
	
		new ViewDeedsGUI();
	}
		
	private void bankruptButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
		
		Object[] options = { "Yes", "No" };
		Object[] winnerOptions = { "New Game", "Quit" };
		
		int x = BoardGUI.dynamicNoImageDialogBox(options, "Are you sure?", "Declare bankruptcy");
		
		if (x == 0) {
			
			board.setActivePlayers(board.getActivePlayers()-1);
			players[board.getCurrentPlayer()].setOut(true);
			
			if (board.getActivePlayers() == 1) {
				
				String name = "";
				
				for (int y = 0; y < board.getPlayerCount(); y++) {
					
					if (players[y].isOut() == false) {
						
						name = players[y].getName();
					}
				}
				
				String text = "The winner is " + name + "!";
				int z = BoardGUI.dynamicNoImageDialogBox(winnerOptions, text, "We have a winner!");
				
				if (z == 0) {
					
					frame.setVisible(false);
					new GameModeGUI();
				}
				
				else {
					
					System.exit(0);
				}
			}
			
			else {
				
				endTurnButton.setEnabled(true);
				rollButton.setEnabled(false);
				fineButton.setEnabled(false);
				useCardButton.setEnabled(false);
				buyCardButton.setEnabled(false);
				propertiesButton.setEnabled(false);
				deedsButton.setEnabled(false);
				bankruptButton.setEnabled(false);
			}
		}
	}
	
	protected static ImageIcon createImageIcon(String path) {
	
        java.net.URL imgURL = BoardGUI.class.getResource(path);
		
        if (imgURL != null) {
		
            return new ImageIcon(imgURL);
        }
		
		else {
		
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }
	
	public static int dynamicDialogBox(Object[] options, String imageURL, String header) {
		
		int x;
		deedLabel.setIcon(createImageIcon(imageURL));
		deedLabel.repaint();
		
		do {
			
			x = JOptionPane.showOptionDialog(frame, deedLabel, header,
        									JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE,
        									null, options, options[0]);
		}
		
		while (x == -1);
        
		return x;
	}
	
	public static int dynamicNoImageDialogBox(Object[] options, String text, String header) {
		
		int x;
		textLabel.setText(text);
		textLabel.repaint();
		
		do {
			
			x = JOptionPane.showOptionDialog(frame, textLabel, header,
        									JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE,
        									null, options, options[0]);
		}
		
		while (x == -1);
        
		return x;
	}
	
	public void loadImages() {
		
		boardURL = "images/Board/board.png";
		
		for (int x = 0; x < 6; x++) {
			
			diceURL[x] = dice.getDiceURL(x);
		}
		
		tokenURL = new String[board.getPlayerCount()];
		
		for (int x = 0; x < board.getPlayerCount(); x++) {
			
			tokenURL[x] = token.getTokenURL(players[x].getToken());
		}
	}
	
	public void rollDice() {
		
		if (players[board.getCurrentPlayer()].getJail() == true) {
			
			fineButton.setEnabled(false);
			useCardButton.setEnabled(false);
			buyCardButton.setEnabled(false);
		}
		
		dice = players[board.getCurrentPlayer()].rollDice();
		
		diceLabel[0].setIcon(createImageIcon(diceURL[dice.getDice1()-1]));
		diceLabel[1].setIcon(createImageIcon(diceURL[dice.getDice2()-1]));
		
		diceLabel[0].repaint();
		diceLabel[1].repaint();
	}
	
	public void moveToken() {
		
		int y = board.getCurrentPlayer();
		
		if (players[y].getJail() == false) {
			
			Dice dice = players[y].getDice();
			int[] z;
			
			players[y].setStop(players[y].getCurrLoc()+dice.getSum());
			
			for (int x = players[y].getCurrLoc(); x < players[y].getStop(); x++) {
				
				z = Location.moveToken(players[y]);
				
				players[y].setXLocation(z[0]);
				players[y].setYLocation(z[1]);
				
				tokenLabel[y].setBounds(z[0], z[1], 15, 14);
				
				players[y] = BoardGUI.setCurrLoc(players[y], x+1);
			}
			
			players[y] = Location.determineLocation(players[y]);
		}
		
		else {
			
			players[y] = Jail.turns(players[y]);
		}
		
		if (Location.getRelocate() == true) {
			
			//System.out.println("Curr: " + players[y].getCurrLoc() + " Next: " + players[y].getNextLoc() + " Stop: " + players[y].getStop());
			
			players[y] = Location.teleportLocation(players[y]);
			tokenLabel[y].setBounds(players[y].getXLocation(), players[y].getYLocation(), 15, 14);
			tokenLabel[y].repaint();
			
			Location.setRelocate(false);

			players[y] = Location.determineLocation(players[y]);
			Board.setIgnoreGo(false);
			
			if (players[y].getJail() == true) {
				
				fineButton.setVisible(true);
				
				if (players[y].getOutOfJailCard1() == true || players[y].getOutOfJailCard2() == true) {
					
					useCardButton.setVisible(true);
				}
				
				else {
					
					buyCardButton.setVisible(true);
				}
			}
		}
		
		playerCash.setText("Cash: " + Integer.toString(players[y].getCash()));
		playerCash.repaint();
	}
	
	public static Player setCurrLoc(Player player, int location) {
		
		if (location < 40) {
			
			player.setCurrLoc(location);
		}
		
		else {
			
			if (location == 40 && Board.getIgnoreGo() == false) {
		
				Object[] okayOption = { "Okay" };
				
				BoardGUI.dynamicDialogBox(okayOption, SpecialTiles.getImageURL(0), SpecialTiles.getName(0));
				player = SpecialTiles.Go(player);
				
				playerCash.setText("Cash: " + Integer.toString(player.getCash()));
				playerCash.repaint();
			}
			
			Board.setIgnoreGo(false);
			player.setCurrLoc(location-40);
		}
		
		return player;
	}
}